/*
 *  +----------------------------------------------------------------------
 *  | sophon [ A FAST GAME FRAMEWORK ]
 *  +----------------------------------------------------------------------
 *  | Copyright (c) 2023-2029 All rights reserved.
 *  +----------------------------------------------------------------------
 *  | Licensed ( http:www.apache.org/licenses/LICENSE-2.0 )
 *  +----------------------------------------------------------------------
 *  | Author: jqiris <1920624985@qq.com>
 *  +----------------------------------------------------------------------
 */

use conhash::ConsistentHash;
use dashmap::DashMap;

pub use pb::*;

use crate::{errors::EncodeError, hash::*};

// @generated
mod pb;

impl From<String> for Server {
    fn from(data: String) -> Self {
        let server: Server = serde_json::from_str(&data).unwrap();
        server
    }
}

pub fn reg_server_item(x: &Server) -> String {
    format!("{}/{}", x.server_type, x.server_id)
}

pub fn reg_server_queue(server_type: &str, queue: &str) -> String {
    format!("{}/{}", server_type, queue)
}

pub fn reg_server_type(x: &Server) -> String {
    x.server_type.to_owned()
}

pub fn reg_server_serialize(x: &Server) -> String {
    serde_json::to_string(x).unwrap()
}

pub fn reg_server_deserialize(data: &str) -> Result<Server, EncodeError> {
    serde_json::from_str(data).map_err(|err| EncodeError::JsonUnmarshalError(err.to_string()))
}

pub struct ServerTypeItem {
    pub hasher: ConsistentHash<HashNode<Server>>,
    pub list: DashMap<String, Server>,
}

impl ServerTypeItem {
    pub fn new() -> Self {
        Self {
            hasher: ConsistentHash::new(),
            list: DashMap::new(),
        }
    }
    pub fn add(&mut self, server: Server) {
        let copyed = server.clone();
        let server_id = server.server_id.clone();
        let node = HashNode::new(server);
        if !self.list.contains_key(server_id.as_str()) {
            self.hasher.add(&node, REPLICAS);
        }
        self.list.insert(copyed.server_id.to_owned(), copyed);
    }
    pub fn remove(&mut self, server: Server) -> bool {
        let server_id = server.server_id.to_owned();
        if self.list.contains_key(&server_id) {
            self.list.remove(&server_id);
            let node = HashNode::new(server);
            self.hasher.remove(&node);
            return true;
        }
        false
    }
}
